package com.lvhx.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

@Api(tags = "1.测试【泛型、枚举】")
@RestController
@RequestMapping("T")
public class TController {

    @ApiOperation("泛型类")
    @GetMapping("/test1")
    public String test1(){

        Box<String> box = new Box<>();
        box.setValue("hello world");
//        box.setValue(1);    // 此处会编译报错

        return "success";
    }

    @ApiOperation("泛型接口")
    @GetMapping("/test2")
    public String test2(){
        StringGenerator generator = new StringGenerator();
        System.out.println(generator.next());

        ArrayGenerator arrayGenerator = new ArrayGenerator(String.class);
        String[] next = (String[]) arrayGenerator.next();
        System.out.println(next.length);

        return "success";
    }


    @ApiOperation("泛型方法")
    @GetMapping("/test3")
    public String test3(){

        String[] stringArray = {"A", "B", "C"};
        // 调用时，编译器通常可以推断出 T 是 String，无需显式指定
        List<String> stringList = fromArrayToList(stringArray);

        Integer[] intArray = {1, 2, 3};
        List<Integer> intList = fromArrayToList(intArray);

        // 如果需要，也可以显式指定类型
        List<Number> numberList = TController.<Number>fromArrayToList(new Number[]{1, 2.5, 3L});

        return "success";
    }

    @ApiOperation("通配符")
    @GetMapping("/test4")
    public String test4(){
        // 无界通配符 <?>

        // 上界通配符 <? extends T>

        // 下界通配符 <? super T>

        /**
         * PECS 原则（Producer-Extends, Consumer-Super）：
         * 这是一个记忆口诀，帮助你决定使用 extends还是 super。
         * 生产者（Producer）：如果你需要一个泛型结构来提供（生产）数据（例如，遍历读取），使用 <? extends T>。
         * 消费者（Consumer）：如果你需要一个泛型结构来接收（消费）数据（例如，添加元素），使用 <? super T>。
         */
        return "success";
    }

    // 多个类型参数的泛型方法
    public static <T, G> List<G> transformList(List<T> list, Function<T, G> function) {
        return list.stream().map(function).collect(Collectors.toList());
    }
    public static <T> List<T> fromArrayToList(T[] array) {
        List<T> list = new ArrayList<>();
        for (T element : array) {
            list.add(element);
        }
        return list;
    }

    // 拷贝函数，src 是生产者（提供数据），dest 是消费者（接收数据）
    public static <T> void copy(List<? extends T> src, List<? super T> dest) {
        for (T item : src) {
            dest.add(item);
        }
    }
}



class Box<T>{
    private T value;

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

interface Generator<T> {
    T next(); // 生成一个 T 类型的对象
}

// 实现泛型接口时，可以指定具体类型
class StringGenerator implements Generator<String> {
    @Override
    public String next() {
        return "Generated String";
    }
}


// 也可以不指定，让实现类自己也成为泛型类
class ArrayGenerator<T> implements Generator<T[]> {
    private Class<T> clazz;

    public ArrayGenerator(Class<T> clazz) {
        this.clazz = clazz;
    }

    @Override
    public T[] next() {
        // 使用反射创建数组的逻辑...
        return (T[]) java.lang.reflect.Array.newInstance(clazz, 10);
    }
}